package com.jh.paymentchannel.util.sdj;

import java.io.ByteArrayInputStream;
import java.io.FileInputStream;
import java.io.InputStream;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.cert.CertPath;
import java.security.cert.CertPathValidator;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.security.cert.PKIXCertPathValidatorResult;
import java.security.cert.PKIXParameters;
import java.security.cert.TrustAnchor;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import javax.crypto.Cipher;

/**
 * 签名工具类
 * @author lwm
 *
 */
public class SignatureTools {
	/**
     * Java密钥库(Java 密钥库，JKS)KEY_STORE
     */
    public static final String KEY_STORE = "JKS";
    
    public static final String X509 = "X.509";
    
    public final static String  CER_PATH = "E:\\sdj_base64.cer"; 
    public final static String  JKS_PATH = "E:\\sdj.jks"; 
    public static final String  PASSWORD = "123456";
    
    
    /**
     * 证书加密
     * @param content
     * @return
     * @throws Exception
     */
    public static String encrypt(String content,String cerCertificatePath)throws Exception {
//    	String cerCertificatePath = PropertiesUtil.getPropertiesValue("certpath.properties", "cer_certificate_path");
       	
    	PublicKey tcsPublicKey = getPublicKey(cerCertificatePath);
        Cipher c1 = Cipher.getInstance(tcsPublicKey.getAlgorithm());
        c1.init(Cipher.ENCRYPT_MODE, tcsPublicKey);
        byte [] bb = c1.doFinal(content.getBytes());
        return  Base64.byteArrayToBase64(bb);
    }
    /**
     * 证书解密
     * @param content
     * @return
     * @throws Exception
     */
    public static String decrypt(String content,String jksCertificatePath,String password)throws Exception{  
//    	String jksCertificatePath = PropertiesUtil.getPropertiesValue("certpath.properties", "jks_certificate_path");
//    	String password = PropertiesUtil.getPropertiesValue("certpath.properties", "password");

    	PrivateKey prikey = getPrivateKey(jksCertificatePath,password);
        Cipher c2 = Cipher.getInstance(prikey.getAlgorithm());  
        c2.init(Cipher.DECRYPT_MODE, prikey);  
        byte[] msg2 = c2.doFinal(Base64.base64ToByteArray(content)); // 解密后的数据  
        // 打印解密字符串  
        String encryptStr = new String (msg2,"utf-8");
        return encryptStr;
    }  
    /**
     * <p>
     * 根据密钥库获得私钥
     * </p>
     * 
     * @param certificatePath 密钥库存储路径
     * @param password 密钥库密码
     * @return
     * @throws Exception
     */
    public static PrivateKey getPrivateKey(String path, String password)throws Exception{
    	KeyStore keyStore = getKeyStore(path, password);
        Enumeration enumas = keyStore.aliases();  
        String alias = null;  
        if (enumas.hasMoreElements())
        {  
        	alias = (String)enumas.nextElement();   
        }  
        return  (PrivateKey) keyStore.getKey(alias, password.toCharArray());  
	}
    
    /**
     * <p>
     * 获得密钥库
     * </p>
     * 
     * @param keyStorePath 密钥库存储路径
     * @param password 密钥库密码
     * @return
     * @throws Exception
     */
    private static KeyStore getKeyStore(String path, String password)throws Exception {
        FileInputStream in = new FileInputStream(path);
        KeyStore keyStore = KeyStore.getInstance(KEY_STORE);
        keyStore.load(in, password.toCharArray());
        in.close();
        return keyStore;
    }
    /**
     * <p>
     * 根据证书获得公钥
     * </p>
     * 
     * @param certificatePath 证书存储路径
     * @return
     * @throws Exception
     */
    private static PublicKey getPublicKey(String path)
            throws Exception {
        Certificate certificate = getCertificate(path);
        PublicKey publicKey = certificate.getPublicKey();
        return publicKey;
    }
    /**
     * <p>
     * 获得证书
     * </p>
     * 
     * @param certificatePath 证书存储路径
     * @return
     * @throws Exception
     */
    private static Certificate getCertificate(String path)
            throws Exception {
        CertificateFactory certificateFactory = CertificateFactory.getInstance(X509);
        FileInputStream in = new FileInputStream(path);
        Certificate certificate = certificateFactory.generateCertificate(in);
        in.close();
        return certificate;
    }
    /**
     * <p>
     * 根据密钥库获得证书
     * </p>
     * 
     * @param keyStorePath 密钥库存储路径
     * @param password 密钥库密码
     * @return
     * @throws Exception
     */
    private static Certificate getCertificate(String path, String password) 
            throws Exception {
        KeyStore keyStore = getKeyStore(path, password);
        Enumeration enumas = keyStore.aliases();  
        String alias = null;  
        if (enumas.hasMoreElements())
        {  
        	alias = (String)enumas.nextElement();   
        }  
        Certificate certificate = keyStore.getCertificate(alias);
        return certificate;
    }
    /**
     * <p>
     * 生成数据签名
     * </p>
     * 
     * @param data 源数据
     * @param certificatePath 密钥库存储路径
     * @param password 密钥库密码
     * @return
     * @throws Exception
     */
    public static String sign(String data, String jksCertificatePath, String password)
    		throws Exception {
        // 获得证书
    	X509Certificate x509Certificate = (X509Certificate) getCertificate(jksCertificatePath,password);
        // 取得私钥
        PrivateKey privateKey = getPrivateKey(jksCertificatePath,password);
        // 构建签名
        Signature signature = Signature.getInstance(x509Certificate.getSigAlgName());
        signature.initSign(privateKey);
        signature.update(data.getBytes());
        byte[] bt = signature.sign();
        return Base64.byteArrayToBase64(bt);
    }
     
    /**
     * <p>
     * 验证签名
     * </p>
     * 
     * @param data 已加密数据
     * @param sign 数据签名[BASE64]
     * @param certificatePath 证书存储路径
     * @return
     * @throws Exception
     */
    public static boolean verifySign(String data, String sign, String certificatePath) 
            throws Exception {
        // 获得证书
        X509Certificate x509Certificate = (X509Certificate) getCertificate(certificatePath);
        // 获得公钥
        PublicKey publicKey = x509Certificate.getPublicKey();
        // 构建签名
        Signature signature = Signature.getInstance(x509Certificate.getSigAlgName());
        signature.initVerify(publicKey);
        signature.update(data.getBytes());
        return signature.verify(Base64.base64ToByteArray(sign));
    }
    public static boolean checkDate(String certificatePath)throws Exception{
    	boolean flag = false;
    	Date date = new Date();
    	 // 获得证书
        try {
        	X509Certificate x509Certificate = (X509Certificate) getCertificate(certificatePath);
			x509Certificate.checkValidity(date);
			flag = true;
		} catch (Exception e) {
			flag = false;
		}
        return flag ;
    }
    /**
     * 字符串Base64编码
     * @param content
     * @return
     * @throws Exception
     */
	public static String base64EncString(String content)throws Exception {
		return Base64.byteArrayToBase64(content.getBytes("UTF-8"));
	}

	/**
	 * 字符串Base64解码
	 * @param content
	 * @return
	 * @throws Exception
	 */
	public static String base64DecString(String content)throws Exception {
		return new String(Base64.base64ToByteArray(content));
	}

    public static boolean checkCertificate(String certificatePath,String jksCertificatePath,String password) throws Exception {
    	KeyStore keyStore = getKeyStore(JKS_PATH, PASSWORD);
        Enumeration enumas = keyStore.aliases();  
        String alias = null;  
        if (enumas.hasMoreElements())
        {  
        	alias = (String)enumas.nextElement();   
        }  
        Certificate clientCertificate = keyStore.getCertificate(alias);
        byte[] CertificateByte = clientCertificate.getEncoded();
        byte[] message = CertificateByte;
        
       //受信任证书链
        CertificateFactory factory = CertificateFactory.getInstance("X509");
        //构建用户证书和CertPath
        ByteArrayInputStream ins = new ByteArrayInputStream(message);
        X509Certificate usercert = (X509Certificate) factory.generateCertificate(ins);
        
        List<Certificate> certList = new ArrayList<Certificate>();
        certList.add(usercert);
        
        CertPath certPath = factory.generateCertPath(certList);
        CertPathValidator validator = CertPathValidator.getInstance("PKIX");
        
       //验证证书链
        String certStorePath = CER_PATH;
        Set<TrustAnchor> trustAnchors = new HashSet<TrustAnchor>();
        InputStream input = new FileInputStream(certStorePath);
        Collection<Certificate> certs = (Collection<Certificate>)factory.generateCertificates(input);
        for (Iterator i = certs.iterator(); i.hasNext();){
            X509Certificate certIt =(X509Certificate)i.next();
            trustAnchors.add(new TrustAnchor(certIt, null));
        }
        //构建证书验证设置
        PKIXParameters parameters = new PKIXParameters(trustAnchors);
        parameters.setRevocationEnabled(false);
        
        PKIXCertPathValidatorResult result = (PKIXCertPathValidatorResult)validator.validate(certPath, parameters);
        
        if(result!=null && checkDate(certificatePath)){
        	return true;
        }
        return false;
    }
    
 
	
}
